package components;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * 
 * @author Anarchee
 *
 */
class GameServer {
	
	private HashMap<String, PrintWriter> players;
	private ArrayBlockingQueue<Socket> sockets;
	private ArrayBlockingQueue<PrintWriter> writers;
	private ServerSocket serverSocket;
	
	public GameServer() {
		writers = new ArrayBlockingQueue<PrintWriter>(3);
		players = new HashMap<String, PrintWriter>();
		initializeSockets();
		runGame();
	}
	
	private void initializeSockets() {
		try {
			serverSocket = new ServerSocket(1234);
		} catch (IOException e) {
			e.getMessage();
			e.printStackTrace();
		}
		sockets = new ArrayBlockingQueue<Socket>(3);
		ListenThread listenThread = new ListenThread();
		listenThread.run();
	}
	
	private void closeSockets() {
		for (Socket socket:sockets) {
			try {
				socket.close();
			} catch (IOException e) {
				System.err.print("******* SOCKET *********");
				e.printStackTrace();
			}
		}
		try {
			serverSocket.close();
		} catch (IOException e) {
			System.err.print("******* SERVER SOCKET *********");
			e.printStackTrace();
		}
	}
	
	@SuppressWarnings("unused")
	private String waitForClient(int secs) {
		String userResponse = null;
		
		
		
		return userResponse;
	}
	
	private void runGame() {
		
		Random generator = new Random(System.currentTimeMillis());
		Rsa rsa = new Rsa(1024);
		
		ArrayList<String> list = new ArrayList<String>(); 
		list.add("Bob");
		list.add("Alice");
		list.add("Eve");
		Collections.shuffle(list);
		
		HashMap<String, BufferedReader> readers = new HashMap<String, BufferedReader>();
		int i = 0;
		for(PrintWriter writer: writers) {
			//writer.println("ALL PLAYERS HAVE CONNECTED!!!\n\n");	
			players.put(list.get(i), writer);
			
			writer.println(list.get(i));	
			i++;
		}
		
		i = 0;
		for(Socket socket: sockets) {
			//writer.println("ALL PLAYERS HAVE CONNECTED!!!\n\n");	
			try {
				readers.put(list.get(i), new BufferedReader(new InputStreamReader(socket.getInputStream())));
			} catch (IOException e) {
				e.printStackTrace();
			}	
			i++;
		}
		
		PrintWriter alice = players.get("Alice");
		PrintWriter bob = players.get("Bob");
		PrintWriter eve = players.get("Eve");
		
		RSAKey privKey = rsa.getRSAPrivKey();
		RSAKey pubKey = rsa.getRSAPrivKey();
		int[] bobsloc = {generator.nextInt(11), generator.nextInt(11)};
		int[] droploc = {generator.nextInt(11), generator.nextInt(11)};
		
		alice.println(pubKey);
		alice.println("(" + bobsloc[0] + "," + bobsloc[1] + ")");
		alice.println("(" + droploc[0] + "," + droploc[1] + ")");
		
		bob.println(privKey);
		bob.println("(" + bobsloc[0] + "," + bobsloc[1] + ")");
		eve.println(pubKey);
		
		int[] bobsGuess = new int[2];
		int[] evesGuess = new int[2];
		
		for(int turn = 0 ; turn < 2 ; turn++) {
			
			String message = null;
			try {
				while(!readers.get("Alice").ready()) {}
				message = readers.get("Alice").readLine();
				System.out.println(message);
				eve.println(message);
				
				while(!readers.get("Eve").ready()) {}
				message = readers.get("Eve").readLine();
				eve.println("Guess x coordinate");
				while(!readers.get("Eve").ready()) {}
				System.out.println(Integer.getInteger(readers.get("Eve").readLine()));
				evesGuess[0] = Integer.getInteger(readers.get("Eve").readLine());
				eve.println("Guess y coordinate");
				while(!readers.get("Eve").ready()) {}
				evesGuess[1] = Integer.getInteger(readers.get("Eve").readLine());
				
				bob.println(message);
				bob.println("Guess x coordinate");
				while(!readers.get("Eve").ready()) {}
				bobsGuess[0] = Integer.getInteger(readers.get("Eve").readLine());
				bob.println("Guess y coordinate");
				while(!readers.get("Eve").ready()) {}
				bobsGuess[1] = Integer.getInteger(readers.get("Eve").readLine());
				
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			
		}
		
		int abscore = 20 - (Math.abs(droploc[0] - bobsGuess[0]) + Math.abs(droploc[0] - bobsGuess[0]));
		int evescore = (Math.abs(droploc[0] - bobsGuess[0]) + Math.abs(droploc[0] - bobsGuess[0]));
		if((evesGuess[0] == droploc[0]) && (evesGuess[1] == droploc[1])) {
			evescore = evescore * 2;
		}
		
		alice.println("Your score is: " + abscore);
		bob.println("Your score is: " + abscore);
		eve.println("Your score is: " + evescore);
		
		for(PrintWriter writer: writers) {
			writer.println("END_GAME");
		}
		closeSockets(); 
	}
	
	
	
	@SuppressWarnings("unused")
	public static void main(String args[]) {
		GameServer server = new GameServer();
	}	
	
	private class ListenThread implements Runnable {

		@Override
		public void run() {
			int i = 0;
			while(i < 3) {
				Socket socket;
				PrintWriter out;
				try {
					socket = serverSocket.accept();
					System.out.println("Connected to client " + ++i);
					sockets.add(socket);
					out = new PrintWriter(socket.getOutputStream(), true);
					writers.add(out);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}	
	}
}
